module ALU_8bit(A, B, ALUop, S, Cout, Zout);
  
  input [7:0] A, B;
  input [2:0] ALUop;
  output [7:0] S;
  output Cout, Zout;
  wire [7:0] wS1, wS2, wS3, wS7, wS8;
  wire w1, w2;
  
  AND_8bit A1(A, B, wS1);
  OR_8bit A2(A, B, wS2);  
  Adder_Substractor_Signed8bit AS3(A, B, 8'b00000000, wS3, w1);
  Adder_Substractor_Signed8bit AS2(A, B, 8'b00000001, wS7, w2);
  Set_on_Lessthan SL1(A, B, wS8);
  
  MUX_8x1 M1(wS1, wS2, wS3, 8'b00000000, 8'b00000000,8'b00000000, wS7, wS8, S, ALUop);
  MUX_8x1 M2(8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, w1, w2, Cout, ALUop);
  
  and G1(Zout, ~S[7], ~S[6], ~S[5], ~S[4], ~S[3], ~S[2], ~S[1], ~S[0]);
  
endmodule

module AND_8bit(i1, i2, out);
  
  input [7:0] i1, i2;
  output [7:0] out;
  
  and A1(out[0], i1[0], i2[0]);
  and A2(out[1], i1[1], i2[1]);
  and A3(out[2], i1[2], i2[2]);
  and A4(out[3], i1[3], i2[3]);
  and A5(out[4], i1[4], i2[4]);
  and A6(out[5], i1[5], i2[5]);
  and A7(out[6], i1[6], i2[6]);
  and A8(out[7], i1[7], i2[7]);

endmodule  

module OR_8bit(i1, i2, out);
  
  input [7:0] i1, i2;
  output [7:0] out;
  
  or O1(out[0], i1[0], i2[0]);
  or O2(out[1], i1[1], i2[1]);
  or O3(out[2], i1[2], i2[2]);
  or O4(out[3], i1[3], i2[3]);
  or O5(out[4], i1[4], i2[4]);
  or O6(out[5], i1[5], i2[5]);
  or O7(out[6], i1[6], i2[6]);
  or O8(out[7], i1[7], i2[7]);
  
endmodule

module MUX_2x1_8bit(i1, i2, out, sel);
  input [7:0]i1, i2;
  input sel;
  output [7:0]out;
  wire [7:0]w1, w2;
  
  and a10(w1[0], i1[0], ~sel);
  and a11(w1[1], i1[1], ~sel);
  and a12(w1[2], i1[2], ~sel);
  and a13(w1[3], i1[3], ~sel);
  and a14(w1[4], i1[4], ~sel);
  and a15(w1[5], i1[5], ~sel);
  and a16(w1[6], i1[6], ~sel);
  and a17(w1[7], i1[7], ~sel);
  
  and a20(w2[0], i2[0], sel);
  and a21(w2[1], i2[1], sel);
  and a22(w2[2], i2[2], sel);
  and a23(w2[3], i2[3], sel);
  and a24(w2[4], i2[4], sel);
  and a25(w2[5], i2[5], sel);
  and a26(w2[6], i2[6], sel);
  and a27(w2[7], i2[7], sel);
  
  or o1(out[0], w1[0], w2[0]);
  or o2(out[1], w1[1], w2[1]);
  or o3(out[2], w1[2], w2[2]);
  or o4(out[3], w1[3], w2[3]);
  or o5(out[4], w1[4], w2[4]);
  or o6(out[5], w1[5], w2[5]);
  or o7(out[6], w1[6], w2[6]);
  or o8(out[7], w1[7], w2[7]);
  
endmodule

module MUX_4x1_8bit(i1, i2, i3, i4, out, sel);
  input [7:0] i1, i2, i3, i4;
  input [1:0]sel;
  output [7:0] out;
  wire [7:0]w1, w2, w3, w4;
  
  MUX_2x1_8bit M1(i1, i2, w1, sel[0]);
  MUX_2x1_8bit M2(i3, i4, w2, sel[0]);
  MUX_2x1_8bit M3(w1, w2, out, sel[1]);  
  
endmodule

module MUX_8x1_8bit(i1, i2, i3, i4, i5, i6, i7, i8, out, sel);
  input [7:0] i1, i2, i3, i4, i5, i6, i7, i8;
  input [2:0]sel;
  output [7:0] out;
  wire [7:0]w1, w2;
  
  MUX_4x1_8bit M1(i1, i2, i3, i4, w1, sel[1:0]);
  MUX_4x1_8bit M2(i5, i6, i7, i8, w2, sel[1:0]);
  MUX_2x1_8bit M3(w1, w2, out, sel[2]);
  
endmodule

module Adder_Substractor_Signed8bit(A, B, Sel, S, Cout);
  
  input [7:0] A, B;
  input Sel;
  output [7:0] S;
  output Cout;
  wire [7:0] wMA, wMB, wavA, wavB, wavApB, wavAmB;
  wire w1, w2;
  
  xor X1(wSel, A[7], B[7]);
  
  Full_Adder_8bit F1(~A, 8'b00000001, 8'b00000000, wMA, w1);
  Full_Adder_8bit F2(~B, 8'b00000001, 8'b00000000, wMB, w2);
  
  MUX_2x1_8bit M1(A, wMA, A[7], wavA);
  MUX_2x1_8bit M2(B, wMB, B[7], wavB);
  
  Adder_Substractor_8bit A1(wavA, wavB, 8'b00000000, wavApB, w3);
  Adder_Substractor_8bit A2(wavA, wavB, 8'b00000001, wavAmB, w4);
  
  Full_Adder_8bit F3(~wavApB, 8'b00000001, 8'b00000000, wMavApB, w5);
  Full_Adder_8bit F4(~wavAmB, 8'b00000001, 8'b00000000, wMavAmB, w6);
  
  MUX_8x1_8bit M3(wavApB, wavAmB, wMavAmB, wMavApB, wavAmB, wavApB, wavMApB, wavMAmB, wSel, S);
  
endmodule

module Half_Adder(A, B, S, C);
  
  input A, B;
  output C, S;
  
  xor X1(S, A, B);
  and A1(A, B);
  
endmodule

module Full_Adder(A, B, Cin, S, Cout);
  
  input A, B, Cin;
  output S, Cout;
  wire w1, w2, w3;
  
  Half_Adder H1(A, B, w1, w2);
  Half_Adder H2(w1, Cin, S, w3);
  
  or O1(Cout, w2, w3);
  
endmodule

module Full_Adder_8bit(A, B, Cin, S, Cout);
  
  input [7:0] A, B;
  input Cin;
  output [7:0] S;
  output Cout;
  wire [7:0] wC;
  
  Full_Adder F1(A[0], B[0], Cin, S[0], wC[0]);
  Full_Adder F2(A[1], B[1], wC[0], S[1], wC[1]);
  Full_Adder F3(A[2], B[2], wC[1], S[2], wC[2]);
  Full_Adder F4(A[3], B[3], wC[2], S[3], wC[3]);
  Full_Adder F5(A[4], B[4], wC[3], S[4], wC[4]);
  Full_Adder F6(A[5], B[5], wC[4], S[5], wC[5]);
  Full_Adder F7(A[6], B[6], wC[5], S[6], wC[6]);
  Full_Adder F8(A[7], B[7], wC[6], S[7], wC[7]);
  
  assign Cout=wC[7];
  
endmodule

module Adder_Substractor_8bit(A, B, Sel, S, Cout);
  
  input [7:0] A, B;
  input Sel;
  output [7:0] S;
  output Cout;
  wire [7:0] wb;
  
  xor X1(wb[7], B[7], ~Sel);
  xor X2(wb[6], B[6], ~Sel);
  xor X3(wb[5], B[5], ~Sel);
  xor X4(wb[4], B[4], ~Sel);
  xor X5(wb[3], B[3], ~Sel);
  xor X6(wb[2], B[2], ~Sel);
  xor X7(wb[1], B[1], ~Sel);
  xor X8(wb[0], B[0], ~Sel);
  
  Full_Adder_8bit A1(A, wb, Sel, S, Cout);
  
endmodule

module Set_on_Lessthan(A, B, Out);
  
  input [7:0] A, B;
  output [7:0] Out;
  wire [7:0] wS;
  wire wC;
  
  Adder_Substractor_Signed8bit AS1(A, B, 8'b00000001, wS, wC);
  
  MUX_2x1_8bit M1(A, B, ~wS[7], Out);
  
endmodule

module Adder_Substractor_Signed8bit(A, B, Sel, S, Cout);
  
  input [7:0] A, B;
  input Sel;
  output [7:0] S;
  output Cout;
  wire [7:0] wMA, wMB, wavA, wavB, wavApB, wavAmB, wavMApB, wavMAmB;
  wire [2:0] wSel;
  wire w1, w2, w3, w4, w5, w6;
  
  Full_Adder_8bit F1(~A, 8'b00000001, 8'b00000000, wMA, w1);
  Full_Adder_8bit F2(~B, 8'b00000001, 8'b00000000, wMB, w2);
  
  MUX_2x1_8bit M1(A, wMA, A[7], wavA);
  MUX_2x1_8bit M2(B, wMB, B[7], wavB);
  
  Adder_Substractor_8bit A1(wavA, wavB, 8'b00000000, wavApB, w3);
  Adder_Substractor_8bit A2(wavA, wavB, 8'b00000001, wavAmB, w4);
  
  Full_Adder_8bit F3(~wavApB, 8'b00000001, 8'b00000000, wMavApB, w5);
  Full_Adder_8bit F4(~wavAmB, 8'b00000001, 8'b00000000, wMavAmB, w6);
  
  assign wSel[2]=Sel;
  assign wSel[1]=A[7];
  assign wSel[0]=B[7];

  MUX_8x1_8bit M3(wavApB, wavAmB, wMavAmB, wMavApB, wavAmB, wavApB, wavMApB, wavMAmB, wSel, S);
  MUX_8x1_8bit_M4(w3, w4, w6, w5, w4, w3, w5, w6, wSel, Cout);
  
endmodule

module Half_Adder(A, B, S, C);
  
  input A, B;
  output C, S;
  
  xor X1(S, A, B);
  and A1(C, A, B);
  
endmodule

module Full_Adder(A, B, Cin, S, Cout);
  
  input A, B, Cin;
  output S, Cout;
  wire w1, w2, w3;
  
  Half_Adder H1(A, B, w1, w2);
  Half_Adder H2(w1, Cin, S, w3);
  
  or O1(Cout, w2, w3);
  
endmodule

module Full_Adder_8bit(A, B, Cin, S, Cout);
  
  input [7:0] A, B;
  input Cin;
  output [7:0] S;
  output Cout;
  wire [7:0] wC;
  
  Full_Adder F1(A[0], B[0], Cin, S[0], wC[0]);
  Full_Adder F2(A[1], B[1], wC[0], S[1], wC[1]);
  Full_Adder F3(A[2], B[2], wC[1], S[2], wC[2]);
  Full_Adder F4(A[3], B[3], wC[2], S[3], wC[3]);
  Full_Adder F5(A[4], B[4], wC[3], S[4], wC[4]);
  Full_Adder F6(A[5], B[5], wC[4], S[5], wC[5]);
  Full_Adder F7(A[6], B[6], wC[5], S[6], wC[6]);
  Full_Adder F8(A[7], B[7], wC[6], S[7], wC[7]);
  
  assign Cout=wC[7];
  
endmodule

module Adder_Substractor_8bit(A, B, Sel, S, Cout);
  
  input [7:0] A, B;
  input Sel;
  output [7:0] S;
  output Cout;
  wire [7:0] wb;
  
  xor X1(wb[7], B[7], ~Sel);
  xor X2(wb[6], B[6], ~Sel);
  xor X3(wb[5], B[5], ~Sel);
  xor X4(wb[4], B[4], ~Sel);
  xor X5(wb[3], B[3], ~Sel);
  xor X6(wb[2], B[2], ~Sel);
  xor X7(wb[1], B[1], ~Sel);
  xor X8(wb[0], B[0], ~Sel);
  
  Full_Adder_8bit A1(A, wb, Sel, S, Cout);
  
endmodule
